﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using NHibernate;
using Studentium.Entities;
using Studentium.Util;

namespace Studentium.UIElements
{
    public partial class StudentInfoTabs : UserControl
    {
        private MainForm mainController;
        private Student currentStudent;
        private StudentsControl studentsControl;
        public MainForm MainController
        {
            get { return mainController; }
            set { mainController = value; }
        }

        public Student CurrentStudent
        {
            get { return currentStudent; }
        }

        public StudentInfoTabs(Student student, StudentsControl studentsControl)
        {
            InitializeComponent();            

            if (studentsControl.StudentMode)
                moveToStudentsBtn.Visible = false;

            this.studentsControl = studentsControl;
            this.mainController = studentsControl.MainController;

            ShowStudentInfos(student);
        }

        private void saveStudentBtn_Click(object sender, EventArgs e)
        {
            bool finishStatusWasSet = personalInfoPanel.WasFinishStatusSet(currentStudent);

            if (!personalInfoPanel.UpdateStudent(currentStudent))
                return;

            currentStudentLbl.Text = currentStudent.FullName;          
            
            // update finish date if finish status was set
            if (finishStatusWasSet)
            {
                currentStudent.FinishDate = DateTime.Now;
            }

            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Update(currentStudent);
                    transaction.Commit();
                }
            }                
            catch (Exception ex)
            {
                Log.log("Error during student update", ex);
                MessageBox.Show("Student cann't be saved - try reopen him/her and update data again or restart application", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);                
            }
            MessageBox.Show("Student info was saved successfully", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        public void ShowStudentInfos(Student student)
        {
            Visible = true;
            currentStudent = student;
            currentStudentLbl.Text = currentStudent.FullName;
            studentTabs.Visible = true;
            personalInfoPanel.LoadStudent(currentStudent);

            if (studentsControl.StudentMode)
            {
                BindingSource source = new BindingSource();
                source.DataSource = new BindingList<Payment>(currentStudent.Payments);
                studentPaymentsGrid.DataSource = source;
                if (studentPaymentsGrid.Columns["StartDate"] != null)
                    studentPaymentsGrid.Columns["StartDate"].DefaultCellStyle.Format = "dd'/'MMMM'/'yyyy";
                if (studentPaymentsGrid.Columns["FinishDate"] != null)
                    studentPaymentsGrid.Columns["FinishDate"].DefaultCellStyle.Format = "dd'/'MMMM'/'yyyy";

                BindingSource source3 = new BindingSource();
                source3.DataSource = new SortableBindingList<ClassAttendance>(currentStudent.Classes);
                classesGrid.DataSource = source3;
                if (classesGrid.Columns["Date"] != null)
                {
                    classesGrid.Columns["Date"].DefaultCellStyle.Format = "dd'/'MMMM'/'yyyy H:mm";                    
                    classesGrid.Sort(classesGrid.Columns["Date"], ListSortDirection.Descending);                    
                }

                oweLbl.Text = currentStudent.Credit.ToString();
                boughtLbl.Text = student.CalcBoughtClasses().ToString();
                wastedLbl.Text = student.CalcWastedClasses().ToString();
            }

            BindingSource source2 = new BindingSource();
            source2.DataSource = new BindingList<Comment>(currentStudent.Comments);
            commentsGrid.DataSource = source2;
            if (commentsGrid.Columns["Date"] != null)
                commentsGrid.Columns["Date"].DefaultCellStyle.Format = "dd'/'MMMM'/'yyyy H:mm";

        }

        internal void UpdateStudentItem(object item)
        {
            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Update(item);
                    transaction.Commit();
                }
            }
            catch(Exception ex)
            {
                Log.log("Error updating student item", ex);
                MessageBox.Show("Cann't update student item - try reaload data again or restart application", "Error",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
            }


            ShowStudent(currentStudent);
        }

        internal void SaveNewStudentItem(object item)
        {
            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Save(item);

                    // add to collection
                    if (item is ClassAttendance)
                    {
                        ClassAttendance attendance = (ClassAttendance) item;
                        attendance.Student.Classes.Add(attendance);                        
                        //attendance.CalendarEntry.ClassAttendances.Add(attendance);                        
                    }
                    else if (item is Comment)
                        ((Comment) item).Student.Comments.Add((Comment) item);
                    else if (item is Payment)
                        ((Payment) item).Student.Payments.Add((Payment) item);

                    transaction.Commit();
                }                
            }
            catch(Exception e)
            {
                Log.log("Error during creation of new student item - " + item.GetType(), e);
                MessageBox.Show(
                    "Cann't create new student item due to error. Please try adding this item again after closing and opening dialog agian",
                    "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);               
            }

            ShowStudent(currentStudent);
        }

        private void ShowStudent(Student student)
        {            
            studentsControl.ShowStudent(student);            
        }

        #region Payments
        private void addStudentPayment_Click(object sender, EventArgs e)
        {
            EditPayment editForm = new EditPayment(new Payment((Student)currentStudent), this, true);
            editForm.Show(Parent);
        }

        private void studentPaymentsGrid_DoubleClick(object sender, EventArgs e)
        {
            Payment payment = (Payment)studentPaymentsGrid.CurrentRow.DataBoundItem;
            EditPayment editForm = new EditPayment(payment, this, false);
            editForm.Show(Parent);
        }

        private void studentPaymentsGrid_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            TryRemoveCurrentRow(studentPaymentsGrid);
            e.Cancel = true;
        }

        private void removePaymentBtn_Click(object sender, EventArgs e)
        {
            TryRemoveCurrentRow(studentPaymentsGrid);
        }
        #endregion

        #region Comments
        private void addCommentBtn_Click(object sender, EventArgs e)
        {
            EditComment editForm = new EditComment(new Comment(currentStudent), this, true);
            editForm.Show(Parent);
        }

        private void commentsGrid_DoubleClick(object sender, EventArgs e)
        {
            Comment comment = (Comment)commentsGrid.CurrentRow.DataBoundItem;
            EditComment editForm = new EditComment(comment, this, false);
            editForm.Show(Parent);
        }

        private void removeCommentBtn_Click(object sender, EventArgs e)
        {
            TryRemoveCurrentRow(commentsGrid);
        }

        private void commentsGrid_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            TryRemoveCurrentRow(commentsGrid);
            e.Cancel = true;
        }
        #endregion

        #region ClassAttendance
        private void addClassBtn_Click(object sender, EventArgs e)
        {
            EditAttendance editForm = new EditAttendance(new ClassAttendance(currentStudent), this, true);
            editForm.Show(Parent);
        }

        private void classesGridView_DoubleClick(object sender, EventArgs e)
        {
            ClassAttendance attendance = (ClassAttendance)classesGrid.CurrentRow.DataBoundItem;

            EditAttendance editForm = new EditAttendance(attendance, this, false);
            editForm.Show(Parent);
        }

        private void classesGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            TryRemoveCurrentRow(classesGrid);
            e.Cancel = true;
        }

        private void removeClassBtn_Click(object sender, EventArgs e)
        {
            TryRemoveCurrentRow(classesGrid);
        }
      #endregion

        private bool TryRemoveCurrentRow(DataGridView itemsGrid)
        {
            if (itemsGrid.CurrentRow == null)
                return false;

            object item = itemsGrid.CurrentRow.DataBoundItem;
            DialogResult result = MessageBox.Show("Are you sure to delete row?", "Warning",
                                                   MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (result == DialogResult.No)
                return false;

            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Delete(item);

                    // remove item from collections because it seems collecitons are cached separately
                    if (item is ClassAttendance)
                    {
                        ClassAttendance attendance = (ClassAttendance)item;
                        currentStudent.Classes.Remove(attendance);
                        //attendance.CalendarEntry.ClassAttendances.Remove(attendance);
                    }
                    else if (item is Comment)
                        currentStudent.Comments.Remove((Comment)item);
                    else if (item is Payment)
                        currentStudent.Payments.Remove((Payment)item);

                    transaction.Commit();
                }
            }
            catch (Exception ex)
            {
                Log.log("Error during student item removal", ex);
                MessageBox.Show("Item cann't be removed now - try reload student info", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);                
            }

            ShowStudent(currentStudent);
            
            
            return true;
        }

        private void moveToStudentsBtn_Click(object sender, EventArgs e)
        {
            currentStudent.BusinessId = studentsControl.GetMaxStudentBusinessId() + 1;
            
            if (!personalInfoPanel.UpdateStudent(currentStudent))
            {
                // validation fail
                currentStudent.BusinessId = 0;
                return;
            }

            try
            {
                using (ISession session = mainController.GetSession())
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Update(currentStudent);
                    transaction.Commit();
                }
            }
            catch (Exception ex)
            {
                Log.log("Error during potiential student to student transmission", ex);
                MessageBox.Show("Cann't move now", "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
            }

            Visible = false;
        }

        internal void RemoveClassesAndPaymentTabs()
        {
            //studentTabs.TabPages["payments"].Visible = false;
            //studentTabs.TabPages["classes"].Visible = false;

            studentTabs.TabPages.RemoveByKey("payments");
            studentTabs.TabPages.RemoveByKey("classes");
        }
    }
}
